之前学习了8个查询单个元素的API,现在开始学习查询多个元素的API。以getAllBy开头的api,如果查找到了,则返回数组;否则报错。

所有getBy开头的API,以getAllBy开头都有:

我们现在只需要关注getAllByRole这个API,其余的可以自行学习。
创建组件Skills:
xxxxxxxxxx171// src\components\Skills\Skills.tsx23import type { SkillsProps } from "./Skills.types";45export const Skills = (props: SkillsProps) => {6 const { skills } = props;78 return (9 <>10 <ul>11 {skills.map((skill) => {12 return <li key={skill}>{skill}</li>;13 })}14 </ul>15 </>16 );17};xxxxxxxxxx51// src\components\Skills\Skills.types.ts23export type SkillsProps = {4 skills: string[]5}编写测试文件:
xxxxxxxxxx201// src\components\Skills\Skills.test.tsx23import { render, screen } from "@testing-library/react";4import { Skills } from "./Skills";56describe("Skills", () => {7 const skills = ["HTML", "CSS", "JavaScript"];89 test("renders correctly", () => {10 render(<Skills skills={skills} />);11 const listElement = screen.getByRole("list"); // ul元素的role=list12 expect(listElement).toBeInTheDocument();13 });1415 test("renders a list of skills", () => {16 render(<Skills skills={skills} />);17 const listItemElements = screen.getAllByRole("listitem"); // li元素的role=listitem18 expect(listItemElements).toHaveLength(skills.length);19 });20});测试OK。

这是我们之前写的查询代码,这些查询API的第一个参数,看上去好像是第一个参数必须是string类型,其实不是。
第一个参数是TextMatch类型,可以是string、regex或者是一个函数。

1、当TextMatch是string类型时

2、当TextMatch是regex时

3、当TextMatch是function时
function应该按照下面这种ts类型来写

如果想要测试没有出现在DOM中的代码,该怎么做呢?
比如说我使用isLoggedIn来条件显示代码,怎么测没有出现在DOM中的代码呢?
x
1// src\components\Skills\Skills.tsx23import { useState } from "react";4import type { SkillsProps } from "./Skills.types";56export const Skills = (props: SkillsProps) => {7 const { skills } = props;8 const [isLoggedIn, setIsLoggedIn] = useState(false);910 return (11 <>12 <ul>13 {skills.map((skill) => {14 return <li key={skill}>{skill}</li>;15 })}16 </ul>17 {isLoggedIn ? (18 <button>Start Learning</button>19 ) : (20 <button onClick={() => setIsLoggedIn(true)}>Login</button>21 )}22 </>23 );24};此时使用getBy前缀的方法,是拿不到<button>Start Learning</button>这个DOM的,所以即使我是这样来测试(.not.toBeInTheDocument()),也会报错:
x
1// src\components\Skills\Skills.test.tsx23test("Start learning button is not rendered", () => {4 render(<Skills skills={skills} />);5 const startLearningButton = screen.getByRole("button", {6 name: "Start learning",7 });8 expect(startLearningButton).not.toBeInTheDocument();9});
这时候就可以使用queryBy...或者queryAllBy...前缀开头的API,getBy...开头的API它们都有相应的。

queryBy... 最常用于测试组件中的 条件渲染(Conditional Rendering),即检查某个元素在特定条件下应该被移除。
queryAllBy... 最常用于测试列表或重复元素,以确认在某种状态下(如列表为空)页面上没有任何该类型的元素出现。
那么测试代码就可以使用queryByRole:
x
1test("Start learning button is not rendered", () => {2 render(<Skills skills={skills} />);3 const startLearningButton = screen.queryByRole("button", {4 name: "Start learning",5 });6 expect(startLearningButton).not.toBeInTheDocument();7});测试OK:


我们之前已经学了:

当你的组件在渲染后不会立即显示某个元素,而需要等待异步操作(如 API 调用、定时器、状态更新)完成后才显示时,该怎么办?
findBy 和 findAllBy 是 React Testing Library (RTL) 中专用于 异步操作 的查询方法。
它们的作用是:在一段等待时间(默认 1000ms 或可配置)内,持续地(45ms 的间隔 内,反复执行查询)查找一个元素,直到找到它,或者超时失败。返回结果是一个 Promise。

在Skills.tsx里面,添加延时操作,0.5s后显示Start learning这个button。

使用findByRole方法:
x
1test("Start learning button is eventually displayed", async () => {2 render(<Skills skills={skills} />);3 const startLearningButton = await screen.findByRole("button", {4 name: "Start learning",5 });6 expect(startLearningButton).toBeInTheDocument();7});测试OK:

下面是findBy...和findAllBy...开头的API的介绍。getBy...开头的API,findBy...和findAllBy...都有。

虽然可以使用之前学过的JS DOM API来获取元素,但是不推荐使用这些方法来测试。还是使用RTL Queries提供的三种类型的方法。

如果测试代码里面有错误,terminal里面的信息也是很详细的。比如说我把button的内文本写错了:

terminal里面的信息给出了提示:

还有两种方法,能够帮助我们进行调试。
作用:将当前在 jsdom 中渲染的整个 DOM 结构(或指定的元素)以易于阅读的字符串形式输出到控制台(console)。

可以看到,两处的dom树结构不一样,这是因为中间使用了promise查询。

作用:扫描当前渲染的 DOM 结构,并将所有元素及其对应的 WAI-ARIA 角色(Role)和可访问性名称(Accessible Name)打印到控制台。
logRoles() 是 RTL 核心哲学 的完美体现:鼓励开发者通过 角色 和 名称 来查询元素。
查找正确的 Role: 当你想使用 getByRole 进行查询,但不确定一个元素到底被识别为哪个角色时(例如,一个自定义组件),logRoles() 可以告诉你准确的角色名称。
验证 Accessible Name: 确保你的交互元素(按钮、链接、输入框)具有正确的 可访问性名称。如果名称不正确,getByRole 或 getByLabelText 就会失败。
发现 ARIA 错误: 它可以帮助你发现哪些元素缺少必要的 ARIA 属性,从而改进组件的可访问性。
调试查询失败: 当 getByRole 失败时,运行 logRoles() 可以直接告诉你这个元素的可访问性名称是什么,你只需将这个名称填入 getByRole 的 name 选项即可。
引入:
x
1import { logRoles } from "@testing-library/react";使用:

输出:

可以看到,会输出元素对应的role属性值和Name值。
这个插件已经没有了,不用管了。

测试同样需要保证用户交互符合预期。

需要使用user-event库。安装:npm i @testing-library/user-event。所有user event的API都是异步的。

虽然RTL里面有fireEvent可以模拟用户操作,但是user-event更牛逼。

这节课学习测试鼠标点击事件。在 @testing-library/user-event 中,"Pointer Interactions"(指针交互)API 涵盖了所有与 鼠标、触摸板或触摸屏 相关的操作。
这些方法旨在模拟用户与屏幕上的元素进行指向和点击的真实行为。
创建组件:
x
1// src\components\Count\Count.tsx23import { useState } from "react";45export const Count = () => {6 const [count, setCount] = useState(0);7 return (8 <>9 <h1>{count}</h1>10 <button onClick={() => setCount(count + 1)}>Increment</button>11 </>12 );13};编写测试文件:
xxxxxxxxxx1371// Count.test.tsx23import { render, screen } from "@testing-library/react";4import { Count } from "./Count";5import userEvent from "@testing-library/user-event";67describe("Count", () => {8 test("renders correctly", () => {9 render(<Count />);10 const countElement = screen.getByRole("heading");11 expect(countElement).toBeInTheDocument();1213 const incrementButton = screen.getByRole("button", {14 name: "Increment",15 });16 expect(incrementButton).toBeInTheDocument();17 });1819 test("renders a count of 0", () => {20 render(<Count />);21 const countElement = screen.getByRole("heading");22 expect(countElement).toHaveTextContent("0");23 });2425 test("render a count of 1 after clicking the increment button", async () => {26 userEvent.setup(); // 初始化userEvent27 render(<Count />);28 const incrementButton = screen.getByRole("button", {29 name: "Increment",30 });31 // 模拟点击事件32 await userEvent.click(incrementButton);33 const countElement = screen.getByRole("heading");34 expect(countElement).toHaveTextContent("1");35 });36});测试OK:

这些API经常使用。

| API | 描述 | 用途 |
|---|---|---|
userEvent.click(element, options) | 模拟完整的 单击 流程 (pointerDown, pointerUp, click 事件链)。 | 最常用的方法,用于激活按钮、链接等。 |
userEvent.dblClick(element, options) | 模拟完整的 双击 流程。 | 用于需要双击才能触发功能的元素。 |
userEvent.tripleClick(element, options) | 模拟完整的 三击 流程。 | 较少用,但用于特殊文本选择功能等。 |
userEvent.hover(element, options) | 模拟鼠标指针悬停在元素上 (pointerOver, mouseOver, pointerEnter, mouseEnter 等)。 | 测试 Tooltip(工具提示)或下拉菜单的显示。 |
userEvent.unhover(element, options) | 模拟鼠标指针离开元素 (pointerOut, mouseOut, pointerLeave, mouseLeave 等)。 | 测试 Tooltip 或下拉菜单的隐藏。 |
以下 API 用于模拟更底层的指针事件,通常用于测试拖放、长按等复杂或自定义的交互逻辑。这些API不经常使用。

这节课学习键盘相关的交互API。
修改Count组件代码,添加input和button。
x
1// src\components\Count\Count.tsx23import { useState } from "react";45export const Count = () => {6 const [count, setCount] = useState(0);7 const [amount, setAmount] = useState(0);8 return (9 <>10 <h1>{count}</h1>11 <button onClick={() => setCount(count + 1)}>Increment</button>12 <input13 type="number"14 name="amount"15 value={amount}16 onChange={(e) => setAmount(parseInt(e.target.value))}17 />18 <button onClick={() => setCount(amount)}>Set</button>19 </>20 );21};编写键盘交互测试代码:

测试OK:








接下来我们学习怎么测试Provider里面的组件,后面几节课会学习测试自定义react hooks。
我们使用mui的theme作为provider。
1、安装:npm install @mui/material @emotion/react @emotion/styled。
2、创建provider文件:
x
1// src\providers\app-providers.tsx23import { CssBaseline } from "@mui/material";4import { ThemeProvider, createTheme } from "@mui/material/styles";56const theme = createTheme({7 palette: {8 mode: "dark",9 },10});1112export const AppProviders = ({ children }: { children: React.ReactNode }) => {13 return (14 <ThemeProvider theme={theme}>15 <CssBaseline />16 {children}17 </ThemeProvider>18 );19};3、创建mui-mode组件,并在App.tsx里面使用它
x
1// App.tsx23import "./App.css";4import { AppProviders } from "./providers/app-providers";5import { MuiMode } from "./components/mui/mui-mode";67function App() {8 return (9 <AppProviders>10 <div className="App">11 <MuiMode />12 </div>13 </AppProviders>14 );15}1617export default App;x
1// src\components\mui\mui-mode.tsx23import { Typography } from "@mui/material";4import { useTheme } from "@mui/material/styles";56export const MuiMode = () => {7 const theme = useTheme();8 return <Typography component="h1">{`${theme.palette.mode} mode`}</Typography>;9};mui-mode组件的意思就是:当设置了provider的mode之后,mui-mode组件会根据provider的值,展示不同的文字。dark mode或者light mode。
4、编写测试文件
重点就是怎么编写matcher里面的值。如果写成这样.toHaveTextContent("dark mode");,会报错。
x
1import { render, screen } from "@testing-library/react";2import { MuiMode } from "./mui-mode";34describe("MuiMode", () => {5 test("renders text correctly", () => {6 render(<MuiMode />);7 const headingElement = screen.getByRole("heading");8 expect(headingElement).toHaveTextContent("dark mode");9 });10});
查看报错信息,可以看到预期是dark mode,但是实际上是light mode。可是我明明provider里面设置的是dark啊。
这是因为在MuiMode组件里面,并没有AppProvider。我们是在App.tsx里面使用的AppProvider,所以当render(<MuiMode />)的时候,接收不到设置的provider。
解决办法:给render方法传递第二个参数,设置wrapper的值为AppProviders。这个意思是在render MuiMode组件之前,使用AppProviders包裹它。
x
1test("renders text correctly", () => {2 render(<MuiMode />, {3 wrapper: AppProviders,4 });5 const headingElement = screen.getByRole("heading");6 expect(headingElement).toHaveTextContent("dark mode");7});测试OK:

也许你会想,在App.tsx中,我们可能会使用到很多Providers,那里面的组件测试时都要先包裹住这些Providers吗?太复杂了吧。有没有一次性定义的方式,让我们在组件测试的时候能不用写wrapper呢?
有,下节课会讲到。
上节课我们提出了一个疑问,既然provider里面的组件都使用到了这个provider,而且provider可能有多个,那岂不是要在每一个测试用例里面写wrapper参数?
testing library提供了一个解决办法:https://testing-library.com/docs/react-testing-library/setup。

编写一个test-utils.tsx的文件,在里面封装自定义的render,这样以后使用render或其它testing-library/react的API,就可以从这个文件引入。
xxxxxxxxxx1161// mui-mode.test.tsx23// 不要从 @testing-library/react 导入方法了4// import { render, screen } from "@testing-library/react";56// 要从定义好的test-utils文件里面导入7import { render, screen } from "../../test-utils";8import { MuiMode } from "./mui-mode";910describe("MuiMode", () => {11 test("renders text correctly", () => {12 render(<MuiMode />);13 const headingElement = screen.getByRole("heading");14 expect(headingElement).toHaveTextContent("dark mode");15 });16});这样测试OK:

这节课学习怎么测试自定义hooks。
1、创建自定义hook
x
221// src\hooks\use-counter\useCounter.types.ts2export type UseCounterProps = {3 initialCount?: number;4}567// src\hooks\use-counter\useCounter.tsx89import { useState } from "react";10import type { UseCounterProps } from "./useCounter.types";1112export const useCounter = ({ initialCount = 0 }: UseCounterProps = {}) => {13 const [count, setCount] = useState(initialCount);14 const increment = () => setCount(count + 1);15 const decrement = () => setCount(count - 1);16 return {17 count,18 increment,19 decrement,20 };21};2、创建测试文件
测试hook不能使用render,要使用renderHook方法。renderHook 的作用就是:
核心属性:
| 属性 | 作用 |
|---|---|
result | 一个对象,包含 Hook 返回的最新值。 |
result.current | 包含 Hook 实际返回的对象或值(例如 { count, increment })。 |
rerender(newProps) | 允许你更新 Hook 的 props,模拟父组件重新渲染。 |
unmount() | 模拟组件卸载,用于测试 useEffect 的清理函数。 |
测试代码:
x
1// src\hooks\use-counter\useCounter.test.tsx23import { renderHook } from "@testing-library/react";4import { useCounter } from "./useCounter";56describe("useCounter", () => {7 test("should render the initial count", () => {8 // 使用renderHook方法来测试react hook9 const { result } = renderHook(useCounter);10 expect(result.current.count).toBe(0);11 });1213 test("should accept and render the same initial count", () => {14 // 可以定义初始值,看输出结果是否符合15 const { result } = renderHook(useCounter, {16 initialProps: {17 initialCount: 10,18 },19 });2021 expect(result.current.count).toBe(10);22 });23});测试OK:

renderHook的initialProps参数:

上节课学习了怎么测试一个react hook的初始值是否符合预期。这节课学习测试hook里面定义的方法。
在写测试代码时,调用hook里面的函数,需要写在act()里面进行调用,这是约定。

测试OK:

这节课开始学习mock测试。使用vitest的fn方法,vi.fn()。
1、创建组件
x
1// src\components\counter-two\counter-two.tsx23type CounterTwoProps = {4 count: number;5 increment: () => void;6 decrement: () => void;7};89export const CounterTwo = ({ count, increment, decrement }: CounterTwoProps) => {10 return (11 <>12 <h1>Counter Two</h1>13 <p>{count}</p>14 {increment && <button onClick={increment}>Increment</button>}15 {decrement && <button onClick={decrement}>Decrement</button>}16 </>17 );18};可以看到,数据是以Props的形式传递过去的。
2、编写测试代码
重点是函数怎么测试,函数只写出了ts类型,但是该怎么测才是正确的方式呢?需要测这些:
如果以后写了组件,不知道该测什么,直接问AI。
x
341// src\components\counter-two\counter-two.test.tsx23import { render, screen } from "@testing-library/react";4import { CounterTwo } from "./counter-two";5import userEvent from "@testing-library/user-event";67describe("CounterTwo", () => {8 test("renders correctly", () => {9 render(<CounterTwo count={0} />);10 const textElement = screen.getByText("Counter Two");11 expect(textElement).toBeInTheDocument();12 });1314 // 这里测试函数是否被调用15 test("handlers are called", async () => {16 userEvent.setup();17 // 使用 vi.fn 来创建两个模拟函数,测试中只需要确认这两个函数被调用过就行了18 const incrementFn = vi.fn();19 const decrementFn = vi.fn();20 render(<CounterTwo count={0} increment={incrementFn} decrement={decrementFn} />);21 const incrementButton = screen.getByRole("button", {22 name: "Increment",23 });24 const decrementButton = screen.getByRole("button", {25 name: "Decrement",26 });2728 await userEvent.click(incrementButton);29 await userEvent.click(decrementButton);30 expect(incrementFn).toHaveBeenCalledTimes(1);31 expect(decrementFn).toHaveBeenCalledTimes(1);32 });33});测试OK:

这节课学习mock http请求。
1、创建组件
x
1// src\components\users\users.tsx23import { useEffect, useState } from "react";45export const Users = () => {6 const [users, setUsers] = useState<string[]>([]);7 const [error, setError] = useState<string | null>(null);89 useEffect(() => {10 fetch("https://jsonplaceholder.typicode.com/users")11 .then((res) => res.json())12 .then((data) => setUsers(data.map((user: { user: string }) => user.name)))13 .catch(() => setError("Error fetching users"));14 }, []);1516 return (17 <div>18 <h1>Users</h1>19 {error && <p>{error}</p>}20 <ul>21 {users.map((user) => (22 <li key={user}>{user}</li>23 ))}24 </ul>25 </div>26 );27};2、编写测试代码
应该测什么呢?
如果数据请求失败,就显示error信息。如果数据请求成功,就显示users信息。
那么测试里面不需要真正请求原始的接口,只需要使用mock请求接口即可。使用https://mswjs.io/提供的工具。下节课会讲到。
这节课我们知道了Mock Http请求需要用到msw,这节课我们来学习设置它。直接参考mswjs.io的文档:https://mswjs.io/docs/quick-start
1、安装依赖npm i msw --save-dev
2、创建请求处理函数
下节课会讲到。
3、流程级集成
这一步就是配置服务器。
x
1// src/mock/server.ts23import { setupServer } from 'msw/node'4import { handlers } from './handlers' // 这里就是处理函数的文件5 6export const server = setupServer(handlers)创建处理函数:
x
1// src\mock\handlers.ts23import { http, HttpResponse } from 'msw'45export const handlers = [6 // 这里的接口地址和组件里面要定义成一样的7 http.get('https://jsonplaceholder.typicode.com/users', () => {8 return HttpResponse.json([9 {10 name: "Bruce Wayne"11 },12 {13 name: "Clark Kent"14 },15 {16 name: "Princess Diana"17 },18 ])19 }),20]为了能在测试的时候,告诉测试页面使用mock接口,需要在setupTests.ts里面,加上这些代码:
注意:MSW是没有管jestdom相关的测试的,所以它单独写了一个vitest.setup.ts的文件。我只需要将它的代码添加到setupTests.ts里面去就行了。

x
101// src\setupTests.ts23import "@testing-library/jest-dom"4import { beforeAll, afterEach, afterAll } from 'vitest'5import { server } from './mock/server'67// 启动 MSW server8beforeAll(() => server.listen())9// 每次测试后重置 handlers(防止状态污染)10afterEach(() => server.resetHandlers())11// 测试结束后关闭12afterAll(() => server.close())接下来就可以写测试代码了:
x
1// src\components\users\users.test.tsx23import { render, screen } from "@testing-library/react";4import { Users } from "./users";56describe("Users", () => {7 test("renders correctly", () => {8 render(<Users />);9 const textElement = screen.getByText("Users");10 expect(textElement).toBeInTheDocument();11 });1213 test("renders a list of users", async () => {14 render(<Users />);15 // 因为在全局启用了 msw server,所以会监听相应的接口请求,会返回handlers里面定义的值16 const users = await screen.findAllByRole("listitem");17 expect(users).toHaveLength(3);18 });19});测试OK:

之前的测试,还没有覆盖接口请求error的情况,这节课来完善。
问题:怎么模拟接口请求错误的情况呢?
使用 server.use() 只在当前测试中替换某个请求的响应,其他测试依然走正常逻辑。
x
1// 23import { render, screen } from "@testing-library/react";4import { Users } from "./users";5import { server } from "../../mock/server";6import { http, HttpResponse } from "msw";78describe("Users", () => {9 test("renders correctly", () => {10 render(<Users />);11 const textElement = screen.getByText("Users");12 expect(textElement).toBeInTheDocument();13 });1415 test("renders a list of users", async () => {16 render(<Users />);17 const users = await screen.findAllByRole("listitem");18 expect(users).toHaveLength(3);19 });2021 test("renders error", async () => {22 // 使用 server.use 来替换请求的响应23 server.use(24 http.get("https://jsonplaceholder.typicode.com/users", () => {25 return new HttpResponse(null, { status: 500 });26 })27 );2829 render(<Users />);30 const error = await screen.findByText("Error fetching users");31 expect(error).toBeInTheDocument();32 });33});测试OK:

这个替换掉的请求,会不会影响正常的请求呢?
不会,因为在superTests.ts里面,我们已经加了afterEach(() => server.resetHandlers()),这句话说明每次请求之后,会重置handlers,所以不会影响。
静态分析测试。
不需要运行代码,就可以检查你的代码是否符合以下期望。

静态测试分析这些方面:代码可读性、持续性、错误处理、类型检查、是否符合最佳实践。总之,就是检查代码写的好不好。

主要有5种工具,其中typescript已经加到项目里面了,一直在用,所以学习剩下的四个。

eslint:“代码的语法警察 + 质量守门员”。它不运行代码,而是“读懂”代码,帮你提前发现问题。

| 作用 | 说明 | 举例 |
|---|---|---|
| 1. 发现潜在 Bug | 找出运行时才会暴露的错误 | if (user = null) → 赋值写成了相等 |
| 2. 强制代码风格统一 | 所有人写法一致 | ' vs "、分号、缩进 |
| 3. 提升可维护性 | 减少“奇技淫巧” | 禁止 eval()、with |
| 4. 强制最佳实践 | 特别是 React Hooks 规则 | useEffect 依赖数组漏写 |
| 5. 自动化 Code Review | 工具先审,人再审 | PR 前自动标记问题 |
| 6. 与编辑器集成,实时提示 | 写代码时红线提醒 | VS Code 实时高亮错误 |
因为项目自带了eslint,所以vscode里面要安装eslint插件来帮助我们。
针对测试,可以安装npm i -D eslint-plugin-jest-dom,来帮助我们分析自己写的jest-dom相关的代码。需要同时配置eslint.config.js,使用的时候找资料即可。
prettier是格式化代码工具,可配置。

使用npm i -D --exact prettier,会安装最新稳定版本的prettier,并且锁定到精确版本号(不会用 ^ 允许小版本升级)。如果要更精准的,那么可以在后面加上具体的版本号prettier@3.3.3。
因为prettier的版本号不同,格式化的风格也会不同,这样一个团队里面的格式化效果就会有区别。
在package.json里面加一条命令:
xxxxxxxxxx1{2 "scripts": {3 4 "format": "prettier --ignore-path .gitignore --write \"**/*.{ts,tsx,css,scss}\""5 }6}忽略掉.gitignore里面不上传到git的文件,然后--write自动修复并保存这些后缀名的文件。
可以使用vscode里面的prettier插件,配置format on save,这样每次保存文件的时候就会格式化,避免每次都要运行命令。
如果eslint和prettier有冲突,可以安装npm i -D eslint-config-prettier,并配置即可。

Husky 是一个 Git Hooks 工具,让你可以在 git commit、git push 等 Git 操作时,自动运行脚本(比如:格式化代码、运行测试、代码检查)。
安装:npm install -D husky
初始化husky:npx husky init,自动创建.husky/pre-commit文件。
配置pre-commit脚本:
x
12. "$(dirname "$0")/_/husky.sh"34npm run format # 自动格式化5npm run lint:fix # 自动修复 ESLint上面使用husky,可以在进行git操作之前,帮助我们格式化、eslint等操作。但是husky会检查整个项目,而我们只需要它帮我们检查修改的文件,怎么办到呢?
使用lint-staged。

lint-staged是一个工具,让你在 git commit 时,只对「被修改的文件(staged files)」运行 lint、format、test 等命令。
1、安装npm install -D lint-staged。
2、在package.json里面添加配置
x
1{2 3 "lint-staged": {4 "*.{js,jsx,ts,tsx}": [5 "eslint --fix",6 "prettier --write"7 ],8 "*.{json,css,scss}": [9 "prettier --write"10 ]11 }12}3、修改pre-commit脚本,现在只需要运行lint-staged即可
412. "$(dirname "$0")/_/husky.sh"34npx lint-staged4、如果想在git push之前运行测试,可以这样配置
创建 pre-push 脚本文件,运行命令npx husky add .husky/pre-push "npm run test",编辑pre-push文件。
x
12. "$(dirname "$0")/_/husky.sh"34# 运行测试,使用单次运行模式,而不是监听模式5npm run test -- --watchAll=falsesection1:介绍了什么是测试?
section2:介绍了jest相关内容
section3-4:介绍了RTL相关内容
section5:怎么测试交互
section6:怎么测试provider相关内容,怎么测试hooks
section7:怎么使用mock进行测试
section8:学习静态分析测试